package com.kaifamiao.io.d0924;

import com.kaifamiao.io.d0923.Bonus;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Properties;

public class MapperedDemo {

    static String url;
    static String user;
    static String password;

    static{
        // 读取配置文件 db.properties
        InputStream in = MapperedDemo.class.getClassLoader().getResourceAsStream("db.properties");
        // 创建 Properties 对象
        Properties properties = new Properties();
        try {
            properties.load(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 从文件中获取数据库连接信息
        String driver = properties.getProperty("driver");
        url = properties.getProperty("url");
        user = properties.getProperty("user");
        password = properties.getProperty("password");
        try {
            // 注册驱动
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        String sql = "SELECT * FROM emp";
        List<Emp> emps = getList(sql, Emp.class);

        emps.stream().forEach(e -> System.out.println(e));
    }


    /**
     *
     * @param sql
     * @param cla
     * @param params
     * @param <T>
     * @return
     */
    public static <T> T getOne(String sql, Class<T> cla, Object...params){
        List<T> list = getList(sql, cla, params);

        return list.size() > 0? list.get(0) : null;
    }

    public static <T> List<T> getList(String sql, Class<T> cla, Object...params){
        List<T> list = new ArrayList<>();
        try {
            // 创建 数据库连接对象
            Connection connection = DriverManager.getConnection(url, user, password);
            PreparedStatement ps = connection.prepareStatement(sql);
            // 设置参数
            for (int i = 0; i < params.length; i ++ ){
                ps.setObject(i + 1, params[i]);
            }

            // 执行查询
            ResultSet resultSet = ps.executeQuery();


            // 结果集映射
            while (resultSet.next()){
                list.add(mapper1(resultSet, cla));
            }

            // 释放资源
            resultSet.close();
            ps.close();
            connection.close();

        } catch (SQLException e) {
            e.printStackTrace();
        }
        return list;
    }


    private static <T> T mapper1(ResultSet resultSet, Class<T> cla){
        try {
            T obj = cla.getConstructor().newInstance();
            // 获取结果集元数据
            ResultSetMetaData metaData = resultSet.getMetaData();
            // 遍历结果集的所有列
            for (int i = 1; i <= metaData.getColumnCount(); i ++){
                // 获取列名 并对列名进行处理
                String label = columnNameToJavaName(metaData.getColumnLabel(i));

                try{
                    // 内省机制
                    PropertyDescriptor pd = new PropertyDescriptor(label, cla);
                    // 获取 写方法 （setter）
                    Method writeMethod = pd.getWriteMethod();

                    // 执行写方法，设置对象的值
                    writeMethod.invoke(obj, resultSet.getObject(i));
                } catch (IntrospectionException e) {
                    e.printStackTrace();
                }

            }
            return obj;
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }


        return null;
    }

    private static <T> T mapper(ResultSet resultSet, Class<T> cla){
        try {
            T obj = cla.getConstructor().newInstance();
            // 获取结果集元数据
            ResultSetMetaData metaData = resultSet.getMetaData();
            // 遍历结果集的所有列
            for (int i = 1; i <= metaData.getColumnCount(); i ++){
                // 获取列名 并对列名进行处理
                String label = columnNameToJavaName(metaData.getColumnLabel(i));

                // 获取列对应的属性
                Field declaredField = cla.getDeclaredField(label);
                // 判断是否可以访问
                if (Modifier.isPrivate(declaredField.getModifiers())){
                    declaredField.setAccessible(true);
                }
                // 设置对象 该属性的值
                declaredField.set(obj, resultSet.getObject(i));
            }
            return obj;
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }


        return null;
    }

    private static String columnNameToJavaName(String columnName){
        if (columnName == null){
            throw new NullPointerException("列名不能为 null");
        }

        // 转小写
        return columnName.toLowerCase(Locale.ROOT);

    }
}
